"""
模块名称: example_mqttclient.py
作者: Lysander.Li
创建时间: 2025 - 11 - 04
最后修改时间: 2025 - 11 - 04
功能描述: MQTT客户端连接示例程序
"""

from umqtt import MQTTClient


class QuecPython_MQTTClient:
    """MQTT客户端应用程序封装类, 提供面向对象的MQTT操作接口
    - 封装了MQTT连接、订阅、发布等基本操作
    - 提供了消息回调机制处理订阅消息
    - 支持SSL/TLS安全连接
    - 包含完善的错误处理机制
    - 适用于物联网设备与MQTT Broker的通信
    """
    
    def __init__(self, client_id, server, port, 
                 user=None, password=None, keepalive=60, ssl=False, ssl_params={}, 
                 reconn=True, version=4):
        """
        初始化MQTT客户端应用
        参数说明:
            client_id (str): 客户端ID, 唯一标识符
            server (str): MQTT Broker服务器地址,可以是域名或IP地址
            port (int): MQTT Broker服务器端口
            user (str, optional): 认证用户名, 用于Broker进行身份验证, 默认为None 
            password (str, optional): 认证密码, 用于Broker进行身份验证, 默认为None
            keepalive (int, optional): 保活时间, 客户端与Broker之间的最大通信间隔
            ssl (bool, optional): 是否使用SSL, 默认为False
            ssl_params (dict, optional): SSL参数
            reconn (bool, optional): 是否自动重连, 默认为True
            version (int, optional): MQTT协议版本, 默认为4 (MQTT 3.1.1)
        """

        self.client_id = client_id
        self.server = server
        self.port = port
        self.user = user
        self.password = password
        self.keepalive = keepalive
        self.ssl = ssl
        self.ssl_params = ssl_params
        self.reconn = reconn
        self.version = version
        
        # MQTT客户端实例
        self.mqtt_client = None
    
    def connect_to_mqtt(self):
        """建立与MQTT Broker的连接
        返回值: 
            bool: 连接成功返回True, 失败返回False
        """
        try:
            self.mqtt_client = MQTTClient(
                # 参数列表参考上述——init——方法
                self.client_id, 
                self.server, 
                self.port,
                user=self.user,
                password=self.password,
                keepalive=self.keepalive,
                ssl=self.ssl,
                ssl_params=self.ssl_params,
                reconn=self.reconn,
                version=self.version
            )
            self.mqtt_client.set_callback(self.on_message_received) # 设置消息回调方法
            self.mqtt_client.connect() # 建立连接
            print("Connected to {}".format(self.server)) 
            return True
        except Exception as e:
            print("MQTT connection failed: {}".format(str(e)))
            return False
    
    def on_message_received(self, topic, msg):
        """
        消息回调处理方法
        参数说明:
            topic (bytes): 接收到消息的主题
            msg (bytes): 接收到的消息
        """
        print("Subscribe Recv: Topic={}, Msg={}".format(topic.decode(), msg.decode()))
    
    def subscribe(self, topic):
        """订阅指定主题"""
        if self.mqtt_client:
            self.mqtt_client.subscribe(topic) # 订阅主题
            print("Subscribed to topic: {}".format(topic.decode()))
    
    def publish(self, topic, message):
        """发布消息到指定主题"""
        if self.mqtt_client:
            self.mqtt_client.publish(topic, message) # 发布消息
            print("Publish topic: {}, msg: {}".format(topic.decode(), message.decode()))

    def disconnect(self):
        """断开MQTT连接"""
        if self.mqtt_client:
            try:
                self.mqtt_client.disconnect() # 断开连接
                print("Disconnected from MQTT server")
            except Exception as e:
                print("Error during disconnect: {}".format(str(e)))
            finally:
                self.mqtt_client = None
    
    def wait_message(self):
        self.mqtt_client.wait_msg()



# 使用示例
if __name__ == '__main__':
    # 创建MQTT客户端应用实例
    cli = QuecPython_MQTTClient(
        client_id="Quecpython_MQTT_Client_01",
        server="101.37.104.185",
        port=44341,
        user="quectel",
        password="12345678",
    )
    cli.connect_to_mqtt()
    cli.subscribe("/public/TEST/quecpython")
    cli.publish("/public/TEST/quecpython", "my name is Quecpython!")
    try:
        while True:
            cli.wait_message()
    except KeyboardInterrupt:
        cli.disconnect()

